<?php
/**
 * Set HTTP status header.
 *
 * @since 1.0
 *
 * @param int $header HTTP status code
 * @return null Does not return anything.
 */
function status_header($header) {
	$text = get_status_header_desc ( $header );
	
	if (empty ( $text )) {
		return false;
	}
	$protocol = $_SERVER ["SERVER_PROTOCOL"];
	if ('HTTP/1.1' != $protocol && 'HTTP/1.0' != $protocol) {
		$protocol = 'HTTP/1.0';
	}
	$status_header = "$protocol $header $text";
	
	return @header ( $status_header, true, $header );
}
/**
 * Retrieve the description for the HTTP status.
 *
 * @since 1.0
 *
 * @param int $code HTTP status code.
 * @return string Empty string if not found, or description if found.
 */
function get_status_header_desc($code) {
	global $output_header_to_desc;
	
	$code = abs ( intval ( $code ) );
	
	if (! isset ( $output_header_to_desc )) {
		$output_header_to_desc = array (100 => 'Continue', 101 => 'Switching Protocols', 102 => 'Processing', 

		200 => 'OK', 201 => 'Created', 202 => 'Accepted', 203 => 'Non-Authoritative Information', 204 => 'No Content', 205 => 'Reset Content', 206 => 'Partial Content', 207 => 'Multi-Status', 226 => 'IM Used', 

		300 => 'Multiple Choices', 301 => 'Moved Permanently', 302 => 'Found', 303 => 'See Other', 304 => 'Not Modified', 305 => 'Use Proxy', 306 => 'Reserved', 307 => 'Temporary Redirect', 

		400 => 'Bad Request', 401 => 'Unauthorized', 402 => 'Payment Required', 403 => 'Forbidden', 404 => 'Not Found', 405 => 'Method Not Allowed', 406 => 'Not Acceptable', 407 => 'Proxy Authentication Required', 408 => 'Request Timeout', 409 => 'Conflict', 410 => 'Gone', 411 => 'Length Required', 412 => 'Precondition Failed', 413 => 'Request Entity Too Large', 414 => 'Request-URI Too Long', 415 => 'Unsupported Media Type', 416 => 'Requested Range Not Satisfiable', 417 => 'Expectation Failed', 422 => 'Unprocessable Entity', 423 => 'Locked', 424 => 'Failed Dependency', 426 => 'Upgrade Required', 

		500 => 'Internal Server Error', 501 => 'Not Implemented', 502 => 'Bad Gateway', 503 => 'Service Unavailable', 504 => 'Gateway Timeout', 505 => 'HTTP Version Not Supported', 506 => 'Variant Also Negotiates', 507 => 'Insufficient Storage', 510 => 'Not Extended' );
	}
	
	if (isset ( $output_header_to_desc [$code] ))
		return $output_header_to_desc [$code];
	else
		return '';
}
/**
 * Appends a trailing slash.
 *
 * Will remove trailing slash if it exists already before adding a trailing
 * slash. This prevents double slashing a string or path.
 *
 * The primary use of this is for paths and thus should be used for paths. It is
 * not restricted to paths and offers no specific path support.
 *
 * @uses untrailingslashit() Unslashes string if it was slashed already.
 *
 * @param string $string What to add the trailing slash to.
 * @return string String with trailing slash added.
 */
function trailingslashit($string) {
	return untrailingslashit ( $string ) . '/';
}
/**
 * Removes trailing slash if it exists.
 *
 * The primary use of this is for paths and thus should be used for paths. It is
 * not restricted to paths and offers no specific path support.
 *
 *
 * @param string $string What to remove the trailing slash from.
 * @return string String without the trailing slash.
 */
function untrailingslashit($string) {
	return rtrim ( $string, '/' );
}
/**
 * Test if a give filesystem path is absolute ('/foo/bar', 'c:\windows').
 *
 *
 * @param string $path File path
 * @return bool True if path is absolute, false is not absolute.
 */
function path_is_absolute($path) {
	// this is definitive if true but fails if $path does not exist or contains a symbolic link
	if (realpath ( $path ) == $path)
		return true;
	
	if (strlen ( $path ) == 0 || $path {0} == '.')
		return false;
		
	// windows allows absolute paths like this
	if (preg_match ( '#^[a-zA-Z]:\\\\#', $path ))
		return true;
		
	// a path starting with / or \ is absolute; anything else is relative
	return ( bool ) preg_match ( '#^[/\\\\]#', $path );
}
/**
 * Join two filesystem paths together (e.g. 'give me $path relative to $base').
 *
 * If the $path is absolute, then it the full path is returned.
 *
 *
 * @param string $base
 * @param string $path
 * @return string The path with the base or absolute path.
 */
function path_join($base, $path) {
	if (path_is_absolute ( $path ))
		return $path;
	
	return rtrim ( $base, '/' ) . '/' . ltrim ( $path, '/' );
}
/**
 * Sanitizes a filename replacing whitespace with dashes
 *
 * Removes special characters that are illegal in filenames on certain
 * operating systems and special characters requiring special escaping
 * to manipulate at the command line. Replaces spaces and consecutive
 * dashes with a single dash. Trim period, dash and underscore from beginning
 * and end of filename.
 *
 * @since 2.1.0
 *
 * @param string $filename The filename to be sanitized
 * @return string The sanitized filename
 */
function sanitize_file_name($filename) {
	$filename_raw = $filename;
	$special_chars = array ("?", "[", "]", "/", "\\", "=", "<", ">", ":", ";", ",", "'", "\"", "&", "$", "#", "*", "(", ")", "|", "~", "`", "!", "{", "}", chr ( 0 ) );
	$filename = str_replace ( $special_chars, '', $filename );
	$filename = preg_replace ( '/[\s-]+/', '-', $filename );
	$filename = trim ( $filename, '.-_' );
	// Split the filename into a base and extension[s]
	$parts = explode ( '.', $filename );
	// Return if only one extension
	if (count ( $parts ) <= 2)
		return $filename;
		
	// Process multiple extensions
	$filename = array_shift ( $parts );
	$extension = array_pop ( $parts );
	
	$mimes = array ('tmp', 'txt', 'jpg', 'gif', 'png', 'rar', 'zip', 'gzip', 'ppt' );
	
	// Loop over any intermediate extensions.  Munge them with a trailing underscore if they are a 2 - 5 character
	// long alpha string not in the extension whitelist.
	foreach ( ( array ) $parts as $part ) {
		$filename .= '.' . $part;
		
		if (preg_match ( "/^[a-zA-Z]{2,5}\d?$/", $part )) {
			$allowed = false;
			foreach ( $mimes as $ext_preg => $mime_match ) {
				$ext_preg = '!(^' . $ext_preg . ')$!i';
				if (preg_match ( $ext_preg, $part )) {
					$allowed = true;
					break;
				}
			}
			if (! $allowed)
				$filename .= '_';
		}
	}
	$filename .= '.' . $extension;
	
	return $filename;
}
/**
 * Get a filename that is sanitized and unique for the given directory.
 *
 * If the filename is not unique, then a number will be added to the filename
 * before the extension, and will continue adding numbers until the filename is
 * unique.
 *
 * The callback must accept two parameters, the first one is the directory and
 * the second is the filename. The callback must be a function.
 *
 * @param string $dir
 * @param string $filename
 * @param string $unique_filename_callback Function name, must be a function.
 * @return string New filename, if given wasn't unique.
 */
function wp_unique_filename($dir, $filename, $unique_filename_callback = null) {
	// sanitize the file name before we begin processing
	$filename = sanitize_file_name ( $filename );
	
	// separate the filename into a name and extension
	$info = pathinfo ( $filename );
	$ext = ! empty ( $info ['extension'] ) ? '.' . $info ['extension'] : '';
	$name = basename ( $filename, $ext );
	
	// edge case: if file is named '.ext', treat as an empty name
	if ($name === $ext)
		$name = '';
		
	// Increment the file number until we have a unique file to save in $dir. Use $override['unique_filename_callback'] if supplied.
	if ($unique_filename_callback && is_callable ( $unique_filename_callback )) {
		$filename = $unique_filename_callback ( $dir, $name );
	} else {
		$number = '';
		
		// change '.ext' to lower case
		if ($ext && strtolower ( $ext ) != $ext) {
			$ext2 = strtolower ( $ext );
			$filename2 = preg_replace ( '|' . preg_quote ( $ext ) . '$|', $ext2, $filename );
			
			// check for both lower and upper case extension or image sub-sizes may be overwritten
			while ( file_exists ( $dir . "/$filename" ) || file_exists ( $dir . "/$filename2" ) ) {
				$new_number = $number + 1;
				$filename = str_replace ( "$number$ext", "$new_number$ext", $filename );
				$filename2 = str_replace ( "$number$ext2", "$new_number$ext2", $filename2 );
				$number = $new_number;
			}
			return $filename2;
		}
		
		while ( file_exists ( $dir . "/$filename" ) ) {
			if ('' == "$number$ext")
				$filename = $filename . ++ $number . $ext;
			else
				$filename = str_replace ( "$number$ext", ++ $number . $ext, $filename );
		}
	}
	
	return $filename;
}
/**
 * Returns a filename of a Temporary unique file.
 * Please note that the calling function must unlink() this itself.
 *
 * The filename is based off the passed parameter or defaults to the current unix timestamp,
 * while the directory can either be passed as well, or by leaving  it blank, default to a writable temporary directory.
 *
 *
 * @param string $filename (optional) Filename to base the Unique file off
 * @param string $dir (optional) Directory to store the file in
 * @return string a writable filename
 */
function wp_tempnam($filename = '', $dir = '') {
	if (empty ( $dir ))
		$dir = trailingslashit ( TMP );
	$filename = basename ( $filename );
	if (empty ( $filename ))
		$filename = time ();
	
	$filename = preg_replace ( '|\..*$|', '.tmp', $filename );
	$filename = $dir . wp_unique_filename ( $dir, $filename );
	touch ( $filename );
	return $filename;
}
/**
 * 输出JS代码,根据浏览器支持情况对JS代码进行压缩.同时可以指定$expires_offset参数对代码进行缓存.
 * @param string $js_content_string 要输出的代码
 * @param boolean $force_gzip 是否强制使用gzip方式压缩
 * @param int $expires_offset 缓存时间
 * @return 直接输出代码
 */
function echo_js($js_content_string, $force_gzip = false, $expires_offset = 31536000) {
	@ob_end_clean ();
	header ( 'Content-Type: application/x-javascript; charset=UTF-8' );
	header ( 'Expires: ' . gmdate ( "D, d M Y H:i:s", time () + $expires_offset ) . ' GMT' );
	header ( "Cache-Control: public, max-age=$expires_offset" );
	$root = defined ( 'SITE_URL' ) ? SITE_URL : '';
	$js_content_string = str_replace ( '$SITE_URL', $root, $js_content_string );
	if (! ini_get ( 'zlib.output_compression' ) && 'ob_gzhandler' != ini_get ( 'output_handler' ) && isset ( $_SERVER ['HTTP_ACCEPT_ENCODING'] )) {
		if (false !== strpos ( strtolower ( $_SERVER ['HTTP_ACCEPT_ENCODING'] ), 'deflate' ) && function_exists ( 'gzdeflate' ) && ! $force_gzip) {
			header ( 'Vary: Accept-Encoding' );
			header ( 'Content-Encoding: deflate' );
			$js_content_string = gzdeflate ( $js_content_string, 3 );
		} elseif (false !== strpos ( strtolower ( $_SERVER ['HTTP_ACCEPT_ENCODING'] ), 'gzip' ) && function_exists ( 'gzencode' )) {
			header ( 'Vary: Accept-Encoding' );
			header ( 'Content-Encoding: gzip' );
			$js_content_string = gzencode ( $js_content_string, 3 );
		}
	}
	echo $js_content_string;
	exit ();
}
/**
 * 输出CSSS代码,根据浏览器支持情况对CSS代码进行压缩.同时可以指定$expires_offset参数对代码进行缓存.
 * @param string $css_content_string 要输出的代码
 * @param boolean $force_gzip 是否强制使用gzip方式压缩
 * @param int $expires_offset 缓存时间
 * @return 直接输出代码
 */
function echo_css($css_content_string, $force_gzip = false, $expires_offset = 31536000) {
	@ob_end_clean ();
	header ( 'Content-Type: text/css' );
	header ( 'Expires: ' . gmdate ( "D, d M Y H:i:s", time () + $expires_offset ) . ' GMT' );
	header ( "Cache-Control: public, max-age=$expires_offset" );
	$root = defined ( 'SITE_URL' ) ? SITE_URL : '';
	$css_content_string = str_replace ( '$SITE_URL', $root, $css_content_string );
	if (! ini_get ( 'zlib.output_compression' ) && 'ob_gzhandler' != ini_get ( 'output_handler' ) && isset ( $_SERVER ['HTTP_ACCEPT_ENCODING'] )) {
		if (false !== strpos ( strtolower ( $_SERVER ['HTTP_ACCEPT_ENCODING'] ), 'deflate' ) && function_exists ( 'gzdeflate' ) && ! $force_gzip) {
			header ( 'Vary: Accept-Encoding' );
			header ( 'Content-Encoding: deflate' );
			$css_content_string = gzdeflate ( $css_content_string, 3 );
		} elseif (false !== strpos ( strtolower ( $_SERVER ['HTTP_ACCEPT_ENCODING'] ), 'gzip' ) && function_exists ( 'gzencode' )) {
			header ( 'Vary: Accept-Encoding' );
			header ( 'Content-Encoding: gzip' );
			$css_content_string = gzencode ( $css_content_string, 3 );
		}
	}
	echo $css_content_string;
	exit ();
}
/**
 * 查找文件
 * @param string $dir 起始目录
 * @param string $pattern 合法的正则表达式,此表达式只用于文件名
 * @param array  $excludes 不包含的目录名
 * @param boolean $recursive 是否递归查找
 * @return array 查找到的文件
 */
function find_files($dir = '.', $pattern = '', $excludes = array(), $recursive = false) {
	$files = array ();
	$dir = trailingslashit ( $dir );
	if (is_dir ( $dir )) {
		$fhd = @opendir ( $dir );
		if ($fhd) {
			while ( $file = readdir ( $fhd ) ) {
				$_excludes = array_merge ( $excludes, array ('.', '..' ) );
				if ($recursive && is_dir ( $dir . $file ) && ! in_array ( $file, $_excludes )) {
					$files = array_merge ( $files, find_files ( $dir . $file, $pattern, $excludes, $recursive ) );
				}
				if (is_file ( $dir . $file ) && @preg_match ( $pattern, $file )) {
					$files [] = $dir . $file;
				}
			}
			@closedir ( $fhd );
		}
	}
	return $files;
}
